﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Ahresty.Algorithms;
using Ahresty.Entity;
using Ahresty.Properties;

namespace Ahresty
{
    class Program
    {
        #region Fields

        #region Const

        /// <summary>
        /// INIファイルの名前
        /// </summary>
        private const string INI_FILE_NAME = "MeshFix.ini";

        /// <summary>
        /// 初期入力ファイルの名前
        /// </summary>
        private const string ORIGINAL_INPUT_FILE_NAME = "input.dat";

        #endregion

        private static IN3DData TargetIn3dData;

        private static Unit[] RelatedUnits;

        private static LineTouch[] LineTouches;

        private static PointTouch[] PointTouches;

        private static Board[] Boards;

        private static Pipe[] Pipes;

        #endregion


        #region Main

        private static void Main(string[] args)
        {
            Program.PreProcess(args);
            
            //Program.AdstefanProcess();
            Program.TargetIn3dData = new IN3DData(@"D:\Documents\Visual Studio 2010\Projects\Ahresty\Ahresty\bin\Release\temp\in3d\heero3.in3d", Parameters.MaterialID);
            
            //Program.DiscontinuousUnitCheckProcess();//Ⅰ-１．鋳物の不連続箇所の検出

            //Program.BoardPipeCheckProcess();//Ⅱ-２．鋳物の薄板及び細管形状要素の検出

            //Program.UnitOccupiedRatioCalcProcess();

            //Program.DiscontinuousUnitFixProcess();//Ⅰ-２．鋳物の不連続箇所を修正

            //Program.BoardPipeFixProcess();//Ⅱ-２．鋳物の薄板及び細管形状要素を修正
            
            Program.IsolatedUnitFixProcess();//Ⅲ．鋳物の孤立要素を検出し、修正

            //Program.SurfaceSmoothProcess();//Ⅳ．鋳物表面のスムージング
            
            Program.OutputProcess();
            
            Logger.Write(Resources.LOG_INFO_PROG_END);
            Console.Read();
        }

        #endregion


        #region Methods

        private static void PreProcess(string[] args)
        {
            //Ⅰ．ワークフォルダの指定
            Parameters.WorkDir = args.Length == 1 && Directory.Exists(args[0]) ? args[0] : Environment.CurrentDirectory;

            //Ⅱ．outputフォルダとtempフォルダを作成
            if (!Directory.Exists(Parameters.OutputDir))
                Directory.CreateDirectory(Parameters.OutputDir);
            if (!Directory.Exists(Parameters.TempDir))
                Directory.CreateDirectory(Parameters.TempDir);

            //Ⅲ．ログファイルを指定・記録開始
            Logger.FilePath = Path.Combine(Parameters.OutputDir, String.Format(@"MeshFix_{0}.log", DateTime.Now.ToString("yyyyMMdd-HHmmss")));

            Logger.Write(Resources.LOG_LOGO, false);
            Logger.Write(Resources.LOG_TAG_PRE_PROCESS_START, false);

            //Ⅴ．設定.iniファイルから実行パラメータを読み取る
            string iniFilePath = Path.Combine(Parameters.WorkDir, Program.INI_FILE_NAME);
            if (!File.Exists(iniFilePath))
            {
                Logger.Write(String.Format(Resources.LOG_ERR_NOT_FOUND_INI_FILE, Parameters.WorkDir, Program.INI_FILE_NAME));
                Environment.Exit(0);
            }

            foreach (string line in File.ReadAllLines(iniFilePath))
            {
                if (line.StartsWith("STLMIXMESSHER=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.StlMixMessherFilePath = line.Substring(14);
                else if (line.StartsWith("OUTLINE=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.OutlineFilePath = line.Substring(8);

                else if (line.StartsWith("LINE_TOUCH=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.LineTouchFlg = line.Substring(11).Equals("ON", StringComparison.InvariantCultureIgnoreCase);
                else if (line.StartsWith("POINT_TOUCH=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.PointTouchFlg = line.Substring(12).Equals("ON", StringComparison.InvariantCultureIgnoreCase);
                else if (line.StartsWith("BOARD=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.BoardFlg = line.Substring(6).Equals("ON", StringComparison.InvariantCultureIgnoreCase);
                else if (line.StartsWith("PIPE=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.PipeFlg = line.Substring(5).Equals("ON", StringComparison.InvariantCultureIgnoreCase);
                else if (line.StartsWith("CONCAVE=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.ConcaveFlg = line.Substring(8).Equals("ON", StringComparison.InvariantCultureIgnoreCase);
                else if (line.StartsWith("PROTUBERANCE=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.ProtuberanceFlg = line.Substring(13).Equals("ON", StringComparison.InvariantCultureIgnoreCase);
                else if (line.StartsWith("ISOLATED=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.IsolatedFlg = line.Substring(9).Equals("ON", StringComparison.InvariantCultureIgnoreCase);

                else if (line.StartsWith("MID=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.MaterialID = (byte)line.ToCharArray()[4];
                else if (line.StartsWith("NID=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.UnknownMaterialID = (byte)line.ToCharArray()[4];
                else if (line.StartsWith("OCCUP=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.ExeCount = int.Parse(line.Substring(6));

                else if (line.StartsWith("DEBUG=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.IsDebugMode = line.Substring(6).Equals("ON", StringComparison.InvariantCultureIgnoreCase);
                else if (line.StartsWith("LINE_TOUCH_ID=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.LineTouchID = (byte)line.ToCharArray()[14];
                else if (line.StartsWith("POINT_TOUCH_ID=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.PointTouchID = (byte)line.ToCharArray()[15];
                else if (line.StartsWith("BOARD_ID=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.BoardID = (byte)line.ToCharArray()[9];
                else if (line.StartsWith("PIPE_ID=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.PipeID = (byte)line.ToCharArray()[8];
                else if (line.StartsWith("CONCAVE_ID=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.ConcaveID = (byte)line.ToCharArray()[11];
                else if (line.StartsWith("PROTUBERANCE_ID=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.ProtuberanceID = (byte)line.ToCharArray()[16];
                else if (line.StartsWith("ISOLATED_ID=", StringComparison.InvariantCultureIgnoreCase))
                    Parameters.IsolatedID = (byte)line.ToCharArray()[12];
            }

            string debugSettingsInfo = Parameters.IsDebugMode ? new StringBuilder().AppendLine(
                    "<LineTouch ID>").AppendLine(" => " + (char)Parameters.LineTouchID).AppendLine(
                    "<PointTouch ID>").AppendLine(" => " + (char)Parameters.PointTouchID).AppendLine(
                    "<Board ID>").AppendLine(" => " + (char)Parameters.BoardID).AppendLine(
                    "<Pipe ID>").AppendLine(" => " + (char)Parameters.PipeID).AppendLine(
                    "<Concave ID>").AppendLine(" => " + (char)Parameters.ConcaveID).AppendLine(
                    "<Protuberance ID>").AppendLine(" => " + (char)Parameters.ProtuberanceID).AppendLine(
                    "<Isolated ID>").AppendLine(" => " + (char)Parameters.IsolatedID).ToString() : String.Empty;

            Logger.Write(String.Format(Resources.LOG_INFO_INI_READ,
                new StringBuilder().AppendLine("<Work Directory>").AppendLine(" => " + Parameters.WorkDir).AppendLine(
                    "<Output Directory>").AppendLine(" => " + Parameters.OutputDir).AppendLine(
                    "<Temporary Directory>").AppendLine(" => " + Parameters.TempDir).AppendLine(
                    "").AppendLine(
                    "<Adstefan Stlmixmessher.exe File>").AppendLine(" => " + Parameters.StlMixMessherFilePath).AppendLine(
                    "<Adstefan Outline.exe File>").AppendLine(" => " + Parameters.OutlineFilePath).AppendLine(
                    "").AppendLine(
                    "<LineTouch Flag>").AppendLine(" => " + (Parameters.LineTouchFlg ? "On" : "Off")).AppendLine(
                    "<PointTouch Flag>").AppendLine(" => " + (Parameters.PointTouchFlg ? "On" : "Off")).AppendLine(
                    "<Board Flag>").AppendLine(" => " + (Parameters.BoardFlg ? "On" : "Off")).AppendLine(
                    "<Pipe Flag>").AppendLine(" => " + (Parameters.PipeFlg ? "On" : "Off")).AppendLine(
                    "<Concave Flag>").AppendLine(" => " + (Parameters.ConcaveFlg ? "On" : "Off")).AppendLine(
                    "<Protuberance Flag>").AppendLine(" => " + (Parameters.ProtuberanceFlg ? "On" : "Off")).AppendLine(
                    "<Isolated Flag>").AppendLine(" => " + (Parameters.IsolatedFlg ? "On" : "Off")).AppendLine(
                    "").AppendLine(
                    "<Material ID>").AppendLine(" => " + (char)Parameters.MaterialID).AppendLine(
                    "<Unknown Material ID>").AppendLine(" => " + (char)Parameters.UnknownMaterialID).AppendLine(
                    "<Occupied Ratio Division Count>").Append(" => " + Parameters.ExeCount).AppendLine(
                    "").AppendLine(
                    "<Debug Mode>").AppendLine(" => " + (Parameters.IsDebugMode ? "On" : "Off")).Append(debugSettingsInfo).ToString(), iniFilePath));

            Logger.Write(Resources.LOG_TAG_PRE_PROCESS_END, false);
        }

        private static void AdstefanProcess()
        {
            Logger.Write(Resources.LOG_TAG_ADSTEFAN_PROCESS_START, false);

            //.dat入力ファイルを使ってin3dファイルを生成し、メッシュデータを取得
            string targetIn3dFilePath = Program.ExecuteStlmixmessher(Program.ORIGINAL_INPUT_FILE_NAME);
            if (String.IsNullOrEmpty(targetIn3dFilePath))
            {
                Logger.Write(Resources.LOG_TAG_ADSTEFAN_PROCESS_END, false);
                Logger.Write(Resources.LOG_INFO_PROG_END);
                Environment.Exit(0);
            }

            Logger.Write(Resources.LOG_INFO_READ_IN3D_START);
            Program.TargetIn3dData = new IN3DData(targetIn3dFilePath, Parameters.MaterialID);
            Logger.Write(Resources.LOG_INFO_READ_IN3D_END);

            Logger.Write(Resources.LOG_TAG_ADSTEFAN_PROCESS_END, false);
        }

        private static void DiscontinuousUnitCheckProcess()
        {
            Logger.Write(Resources.LOG_TAG_CHECK_DISCONTINUOUS_UNIT_PROCESS_START, false);

            DateTime startDt, endDt;

            if (Parameters.LineTouchFlg)
            {
                Logger.Write(Resources.LOG_INFO_CHECK_LINE_TOUCH_START);
                startDt = DateTime.Now;
                Program.LineTouches = LineTouchHandler.LookForLineTouchs(Program.TargetIn3dData);
                //Console.WriteLine(LineTouchHandler.LookForLineTouchCount(Program.TargetIn3dData));
                endDt = DateTime.Now;
                Logger.Write(String.Format(Resources.LOG_INFO_CHECK_LINE_TOUCH_END, Math.Round((endDt - startDt).TotalSeconds, 2), Program.LineTouches.Length));
            }
            else
                Logger.Write(Resources.LOG_INFO_CHECK_LINE_TOUCH_SKIP);

            if (Parameters.PointTouchFlg)
            {
                Logger.Write(Resources.LOG_INFO_CHECK_POINT_TOUCH_START);
                startDt = DateTime.Now;
                Program.PointTouches = PointTouchHandler.LookForPointTouchs(Program.TargetIn3dData);
                //Console.WriteLine(PointTouchHandler.LookForPointTouchCount(Program.TargetIn3dData));
                endDt = DateTime.Now;
                Logger.Write(String.Format(Resources.LOG_INFO_CHECK_POINT_TOUCH_END, Math.Round((endDt - startDt).TotalSeconds, 2), Program.PointTouches.Length));
            }
            else
                Logger.Write(Resources.LOG_INFO_CHECK_POINT_TOUCH_SKIP);

            Logger.Write(Resources.LOG_TAG_CHECK_DISCONTINUOUS_UNIT_PROCESS_END, false);
        }

        private static void BoardPipeCheckProcess()
        {
            Logger.Write(Resources.LOG_TAG_CHECK_BOARD_PIPE_PROCESS_START, false);

            DateTime startDt, endDt;

            if (Parameters.BoardFlg)
            {
                Logger.Write(Resources.LOG_INFO_CHECK_BOARD_START);
                startDt = DateTime.Now;
                Program.Boards = BoardHandler.LookForBoards(Program.TargetIn3dData);
                //Console.WriteLine(BoardHandler.LookForBoardCount(Program.TargetIn3dData));
                endDt = DateTime.Now;
                Logger.Write(String.Format(Resources.LOG_INFO_CHECK_BOARD_END, Math.Round((endDt - startDt).TotalSeconds, 2), Program.Boards.Length));
            }
            else
                Logger.Write(Resources.LOG_INFO_CHECK_BOARD_SKIP);

            if (Parameters.PipeFlg)
            {
                Logger.Write(Resources.LOG_INFO_CHECK_PIPE_START);
                startDt = DateTime.Now;
                Program.Pipes = PipeHandler.LookForPipes(Program.TargetIn3dData);
                //Console.WriteLine(PipeHandler.LookForPipeCount(Program.TargetIn3dData));
                endDt = DateTime.Now;
                Logger.Write(String.Format(Resources.LOG_INFO_CHECK_PIPE_END, Math.Round((endDt - startDt).TotalSeconds, 2), Program.Pipes.Length));
            }
            else
                Logger.Write(Resources.LOG_INFO_CHECK_PIPE_SKIP);

            Logger.Write(Resources.LOG_TAG_CHECK_BOARD_PIPE_PROCESS_END, false);
        }

        private static void UnitOccupiedRatioCalcProcess()
        {
            Logger.Write(Resources.LOG_TAG_UNIT_OCC_RATIO_CALC_PROCESS_START, false);

            double initOccupiedRatio = 0.5d;//初期占有率
            string[] lines = File.ReadAllLines(Path.Combine(Parameters.WorkDir, Program.ORIGINAL_INPUT_FILE_NAME));
            int stlCount = int.Parse(lines[0]);//STLファイル数
            for (int n = 0; n < stlCount; n++)
                if (lines[n * 3 + 2].ToCharArray()[0] == Parameters.MaterialID)
                {
                    initOccupiedRatio = double.Parse(lines[n * 3 + 3]);
                    break;
                }

            string[] tempIn3dFiles = Program.ExecuteStlMixmessherByMultiOccupiedRatios(initOccupiedRatio, Parameters.ExeCount);

            List<Unit> relatedUnitList = new List<Unit>();
            if (Parameters.LineTouchFlg)
                foreach (LineTouch lt in Program.LineTouches)
                    relatedUnitList.AddRange(new Unit[] { lt.FixCandidate1, lt.FixCandidate2, });
            if (Parameters.PointTouchFlg)
                foreach (PointTouch pt in Program.PointTouches)
                    relatedUnitList.AddRange(pt.FixCandidates1.Union(pt.FixCandidates2).Union(pt.FixCandidates3));
            if (Parameters.BoardFlg)
                foreach (Board b in Program.Boards)
                    relatedUnitList.AddRange(b.FixCandidates1.Union(b.FixCandidates2));
            if (Parameters.PipeFlg)
                foreach (Pipe p in Program.Pipes)
                    relatedUnitList.AddRange(p.FixCandidates1.Union(p.FixCandidates2).Union(p.FixCandidates3).Union(p.FixCandidates4));

            Program.RelatedUnits = Unit.GetUnitsInfo(relatedUnitList.Distinct().ToArray(), tempIn3dFiles, Parameters.MaterialID);

            Logger.Write(Resources.LOG_TAG_UNIT_OCC_RATIO_CALC_PROCESS_END, false);
        }

        private static void DiscontinuousUnitFixProcess()
        {
            Logger.Write(Resources.LOG_TAG_FIX_DISCONTINUOUS_UNIT_PROCESS_START, false);

            if (Parameters.LineTouchFlg)
            {
                Logger.Write(Resources.LOG_INFO_FIX_LINE_TOUCH_START);
                foreach (LineTouch lt in Program.LineTouches)
                    LineTouchHandler.FixLineTouch(lt, Program.RelatedUnits, ref Program.TargetIn3dData, Parameters.IsDebugMode ? Parameters.LineTouchID : Parameters.MaterialID);
                Logger.Write(Resources.LOG_INFO_FIX_LINE_TOUCH_END);
            }
            else
                Logger.Write(Resources.LOG_INFO_FIX_LINE_TOUCH_SKIP);

            if (Parameters.PointTouchFlg)
            {
                Logger.Write(Resources.LOG_INFO_FIX_POINT_TOUCH_START);
                foreach (PointTouch pt in Program.PointTouches)
                    PointTouchHandler.FixPointTouch(pt, Program.RelatedUnits, ref Program.TargetIn3dData, Parameters.IsDebugMode ? Parameters.PointTouchID : Parameters.MaterialID);
                Logger.Write(Resources.LOG_INFO_FIX_POINT_TOUCH_END);
            }
            else
                Logger.Write(Resources.LOG_INFO_FIX_POINT_TOUCH_SKIP);

            Logger.Write(Resources.LOG_TAG_FIX_DISCONTINUOUS_UNIT_PROCESS_END, false);
        }

        private static void BoardPipeFixProcess()
        {
            Logger.Write(Resources.LOG_TAG_FIX_BOARD_PIPE_PROCESS_START, false);

            if (Parameters.BoardFlg)
            {
                Logger.Write(Resources.LOG_INFO_FIX_BOARD_START);
                foreach (Board b in Program.Boards)
                    BoardHandler.FixBoard(b, Program.RelatedUnits, ref Program.TargetIn3dData, Parameters.IsDebugMode ? Parameters.BoardID : Parameters.MaterialID);
                Logger.Write(Resources.LOG_INFO_FIX_BOARD_END);
            }
            else
                Logger.Write(Resources.LOG_INFO_FIX_BOARD_SKIP);

            if (Parameters.PipeFlg)
            {
                Logger.Write(Resources.LOG_INFO_FIX_PIPE_START);
                foreach (Pipe p in Program.Pipes)
                    PipeHandler.FixPipe(p, Program.RelatedUnits, ref Program.TargetIn3dData, Parameters.IsDebugMode ? Parameters.PipeID : Parameters.MaterialID);
                Logger.Write(Resources.LOG_INFO_FIX_PIPE_END);
            }
            else
                Logger.Write(Resources.LOG_INFO_FIX_PIPE_SKIP);

            Logger.Write(Resources.LOG_TAG_FIX_BOARD_PIPE_PROCESS_END, false);
        }

        private static void IsolatedUnitFixProcess()
        {
            Logger.Write(Resources.LOG_TAG_FIX_ISOLATED_UNIT_PROCESS_START, false);

            if (Parameters.IsolatedFlg)
            {
                Logger.Write(Resources.LOG_INFO_FIX_ISOLATED_UNIT_START);
                NewGroupUnitHandler.FixIsolatedUnits(ref Program.TargetIn3dData,
                    Parameters.IsDebugMode ? Parameters.IsolatedID : Parameters.MaterialID,
                    Parameters.IsDebugMode ? Parameters.IsolatedID : Parameters.AirMaterialID);
                Logger.Write(Resources.LOG_INFO_FIX_ISOLATED_UNIT_END);
            }
            else
                Logger.Write(Resources.LOG_INFO_ISOLATED_UNIT_SKIP);

            Logger.Write(Resources.LOG_TAG_FIX_ISOLATED_UNIT_PROCESS_END, false);
        }

        private static void SurfaceSmoothProcess()
        {
            Logger.Write(Resources.LOG_TAG_SURFACE_SMOOTH_PROCESS_START, false);

            DateTime startDt, endDt;

            if (Parameters.ConcaveFlg)
            {
                Logger.Write(Resources.LOG_INFO_CHECK_CONCAVE_START);
                startDt = DateTime.Now;
                Unit[] concaves = ConcaveHandler.LookForConcaves(Program.TargetIn3dData);
                //Console.WriteLine(ConcaveHandler.LookForConcaveCount(Program.TargetIn3dData));
                endDt = DateTime.Now;
                Logger.Write(String.Format(Resources.LOG_INFO_CHECK_CONCAVE_END, Math.Round((endDt - startDt).TotalSeconds, 2), concaves.Length));

                Logger.Write(Resources.LOG_INFO_FIX_CONCAVE_START);
                foreach (Unit c in concaves)
                    ConcaveHandler.FixConcave(ref Program.TargetIn3dData, c, Parameters.IsDebugMode ? Parameters.ConcaveID : Parameters.MaterialID);
                Logger.Write(Resources.LOG_INFO_FIX_CONCAVE_END);
            }
            else
                Logger.Write(Resources.LOG_INFO_CONCAVE_SKIP);

            if (Parameters.ProtuberanceFlg)
            {
                Logger.Write(Resources.LOG_INFO_CHECK_PROTUBERANCE_START);
                startDt = DateTime.Now;
                Unit[] protuberances = ProtuberanceHandler.LookForProtuberances(Program.TargetIn3dData);
                //Console.WriteLine(ProtuberanceHandler.LookForProtuberanceCount(Program.TargetIn3dData));
                endDt = DateTime.Now;
                Logger.Write(String.Format(Resources.LOG_INFO_CHECK_PROTUBERANCE_END, Math.Round((endDt - startDt).TotalSeconds, 2), protuberances.Length));

                Logger.Write(Resources.LOG_INFO_FIX_PROTUBERANCE_START);
                foreach (Unit p in protuberances)
                    ProtuberanceHandler.FixProtuberance(ref Program.TargetIn3dData, p, Parameters.IsDebugMode ? Parameters.ProtuberanceID : Parameters.AirMaterialID);
                Logger.Write(Resources.LOG_INFO_FIX_PROTUBERANCE_END);
            }
            else
                Logger.Write(Resources.LOG_INFO_PROTUBERANCE_SKIP);

            Logger.Write(Resources.LOG_TAG_SURFACE_SMOOTH_PROCESS_END, false);
        }

        private static void OutputProcess()
        {
            Logger.Write(Resources.LOG_TAG_OUTPUT_PROCESS_START, false);

            string outputFilaPath = Path.Combine(Parameters.OutputDir, "new.in3d");
            Logger.Write(Resources.LOG_INFO_OUTPUT_START);
            Program.TargetIn3dData.Output(outputFilaPath);
            Logger.Write(String.Format(Resources.LOG_INFO_OUTPUT_END, outputFilaPath));

            Logger.Write(Resources.LOG_TAG_OUTPUT_PROCESS_END, false);
        }

        /// <summary>
        /// 指定の入力ファイルでADSTEFANの「stlmixmessher.exe」を実行
        /// </summary>
        /// <param name="inputFileRelativePath">入力ファイルの相対パス</param>
        /// <returns>生成された.in3dファイルのパス</returns>
        private static string ExecuteStlmixmessher(string inputFileRelativePath)
        {
            string in3dFilePath = String.Empty;

            try
            {
                Logger.Write(String.Format(Resources.LOG_INFO_STLMIXMESSHER_START, Path.Combine(Parameters.WorkDir, inputFileRelativePath)));

                StlmixmessherHandler.ExecuteOutline(Parameters.WorkDir, Parameters.OutlineFilePath, inputFileRelativePath);

                in3dFilePath = StlmixmessherHandler.ExecuteStlmixmessher(
                    Parameters.WorkDir, Parameters.StlMixMessherFilePath, inputFileRelativePath);

                if (!String.IsNullOrEmpty(in3dFilePath))
                    Logger.Write(String.Format(Resources.LOG_INFO_STLMIXMESSHER_NORMAL_END, in3dFilePath));
                else
                    Logger.Write(Resources.LOG_INFO_STLMIXMESSHER_ERROR_END);
            }
            catch (Exception ex)
            {
                Logger.Write(String.Format(Resources.LOG_ERR_STLMIXMESSHER_EXE, ex.Message, ex.StackTrace));
            }

            return in3dFilePath;
        }

        /// <summary>
        /// 指定の占有率でADSTEFANの「stlmixmessher.exe」を実行
        /// </summary>
        /// <param name="occupiedRatio">占有率</param>
        /// <returns>生成された.in3dファイルのパス</returns>
        private static string ExecuteStlmixmessherByOccupiedRatio(double occupiedRatio)
        {
            List<string> contents = new List<string>();

            string[] lines = File.ReadAllLines(Path.Combine(Parameters.WorkDir, Program.ORIGINAL_INPUT_FILE_NAME));

            int lineIndex = 0;
            int stlCount = int.Parse(lines[0]);//STLファイル数
            contents.Add(lines[0]);
            lineIndex++;
            for (int n = 0; n < stlCount; n++)
            {
                contents.Add(lines[lineIndex]);//STLデータファイル名称
                lineIndex++;

                contents.Add(lines[lineIndex]);//材料番号
                lineIndex++;

                if (lines[n * 3 + 2].ToCharArray()[0] == Parameters.MaterialID)//占有率
                    contents.Add(occupiedRatio.ToString());
                else
                    contents.Add(lines[lineIndex]);
                lineIndex++;
            }

            contents.Add(String.Format(@"temp\in3d\{0}.in3d", occupiedRatio.ToString().Substring(2)));//IN3Dの出力ファイルのパスと名称
            lineIndex++;

            for (int n = lineIndex; n < lines.Length; n++)
                contents.Add(lines[n]);

            string inputFileName = String.Format(@"{0}.dat", occupiedRatio.ToString().Substring(2));
            File.WriteAllLines(Path.Combine(Parameters.TempDir, inputFileName), contents.ToArray());

            return Program.ExecuteStlmixmessher(String.Format(@"temp\{0}", inputFileName));
        }

        /// <summary>
        /// 指定の初期占有率と実行回数でADSTEFANの「stlmixmessher.exe」を実行
        /// </summary>
        /// <param name="initOccupiedRatio">初期占有率</param>
        /// <param name="exeCount">実行回数</param>
        /// <returns>生成された.in3dファイルのパス集合</returns>
        private static string[] ExecuteStlMixmessherByMultiOccupiedRatios(double initOccupiedRatio, int exeCount)
        {
            List<string> in3dFiles = new List<string>();

            List<double> occs = new List<double>();
            occs.Add(0);
            occs.Add(initOccupiedRatio);
            occs.Add(1);

            for (int n = 0; n < exeCount; n++)
            {
                List<double> newOccs = new List<double>();

                for (int m = 1; m < occs.Count; m++)
                    newOccs.Add((occs[m] - occs[m - 1]) / 2 + occs[m - 1]);

                occs.AddRange(newOccs);
                occs.Sort();
            }

            foreach (double occ in occs)
                if (occ != 0 && occ != 1 && occ != initOccupiedRatio)
                    in3dFiles.Add(Program.ExecuteStlmixmessherByOccupiedRatio(occ));

            return in3dFiles.ToArray();
        }

        #endregion
    }
}